package com.leilbase.authshiro.realm;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.leilbase.authshiro.auth.entity.User;
import com.leilbase.authshiro.auth.service.impl.PermissionServiceImpl;
import com.leilbase.authshiro.auth.service.impl.RoleServiceImpl;
import com.leilbase.authshiro.auth.service.impl.UserServiceImpl;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.sql.Wrapper;
import java.util.*;
import java.util.stream.Collectors;

public class CustomRealm extends AuthorizingRealm {

    private final Logger logger = LoggerFactory.getLogger(CustomRealm.class);

    @Value("${leilbase.auth.salt}")
    String salt;

    @Autowired
    UserServiceImpl userService;

    /**
     * 获取授权信息
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        // 从认证信息中获取用户名
        String name = (String) principalCollection.getPrimaryPrincipal();
        logger.error("realm中用户的姓名：" + name);
        // 从数据库中获取角色信息和权限信息
        List<Map<String, Object>> mapList = userService.listUserRolePermissionMapsByName(name);
        Set<String> permissions = mapList.stream()
                .map(map -> (String) map.get("permission"))
                .collect(Collectors.toSet());
        Set<String> roles = mapList.stream()
                .map(map -> (String) map.get("role"))
                .collect(Collectors.toSet());
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();

        authorizationInfo.setRoles(roles);
        authorizationInfo.setStringPermissions(permissions);
        return authorizationInfo;
    }

    /**
     * 获取认证信息
     * @param authenticationToken
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        String name = (String) authenticationToken.getPrincipal();
        Map<String, Object> info = userService
                .getMap(Wrappers.<User>lambdaQuery()
                .select(User::getPassword)
                .eq(User::getName, name));
        String password = (String) info.get("password");
        if (password != null) {
            SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(name, password, "CustomRealm");
            // 为认证方法设置盐值
            simpleAuthenticationInfo.setCredentialsSalt(ByteSource.Util.bytes(this.salt));
            return simpleAuthenticationInfo;
        }

        return null;
    }
}
